我想大家看到前一天的範例,應該會有這種感覺吧
唉呦,很猛嘛~
[coroutine]對呀,我超厲害的啦
這code的簡潔度,很勇喔!!
聽話,讓我看看
[coroutine]你在幹嘛,不要啦
特此聲明,本系列文章沒有任何coroutine遭到迫害
一個完整的Coroutine Scope是由下列幾個東西組成
而他們在CoroutineScope的建構式裡,可以透過+聲明建構參數,這邊建構參數中Dispatcher和Name有默認值,CoroutineExceptionHandler則沒有,Job()就得看你是實現哪種Scope,以CoroutineScope來說,需要一個Job()
CoroutineScope(Job() + Dispatchers.IO)
// or
val scope = CoroutineScope(Job())
val job = scope.launch{
}
...
scope.cancel()
每當我們創建一個Coroutine,他會返回一個Job,讓我們可以識別並控制Coroutine的生命週期,而我們也可以自己實例一個Job,作為Coroutine context的參數傳入,並透過這個Job管理coroutine
但回傳的job一定不會一樣,因為系統始終會分配新的job,coroutine 的父子繼承關係,我明天會講個詳細,先記住就好
Parent CoroutineContext explained
https://www.kotlincn.net/docs/reference/coroutines/coroutine-context-and-dispatchers.html
-IO
在主線程之外執行磁碟或網路請求,例如使用room, 從文件中讀取數據或往文件寫入數據,不同的網路操作等等
-Main
用於和界面交互和快速執行的工作,調用suspend方法、更新livedata對象等等
-Default
主線程之外,大量運用cpu資源運算的工作,如資料排序或解析json,DiffUtil等等
-Unconfined
不指定,通常會在當前的thread執行
更深入看dispatcher,jast帶你看源碼
在coroutine,任何操作如果 throw Exception,會被交由parent coroutine,然後再交給parent coroutine的parent coroutine,直到root,細節會在之後開一篇出來
為什麼這邊都用淺談的呢?
因為我覺得很重要,但全部都在這邊講又太多了,這邊就先給個概念
前面介紹完CoroutineScope的建構和繼承,現在講講我們為什麼要實例他
一個CoroutineScope會持續追蹤所有開發者launch或Async產生的coroutine,CoroutineScope不運行coroutine,更像是創造一個讓協程運行的作用域,,而開發者需要透過launch, async去啟用coroutine
那這樣有甚麼好處嗎?
有的,當我們針對root CoroutineScope執行scope.cancel()時,所有在他之下的Coroutine都會被取消,這是structured concurrency的特性
為了確保所有coroutine都被追蹤,kotlin僅允許以coroutineScope創建coroutine,簡單說的話,沒有scope,你用不了coroutine
某些ktx package提供了生命週期相關的coroutineScope,像是viewModelScope或是LifeCycleScope,他們是由官方提供的特殊CoroutineScope,因為他們會跟著lifecycle自動取消,而我們同樣可以創建自己的coroutineScope
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun exampleMethod() {
// Starts a new coroutine within the scope
scope.launch {
// New coroutine that can call suspend functions
fetchDocs()
}
}
fun cleanUp() {
// Cancel the scope to cancel ongoing coroutines work
//已取消的作用域將無法在創建協程
scope.cancel()
}
非常重要的一點,如果你自己創建了CoroutineScope,但不去cancel掉,這個coroutine並不會被gc回收
這邊說不會被回收-stackoverFlow